package com.onpositive.units;

import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.Locale;

import org.w3c.dom.Element;
import org.w3c.dom.Node;

import com.onpositive.data.units.DateWithAccuracy;
import com.onpositive.knowledge.model.values.IHasValue;

public class ParsedDate extends RangeValue<DateWithAccuracy> {
	/**
	 * 
	 */
	private static final long serialVersionUID = -3427689516346273326L;

	public static final String ID = "date";

	public ParsedDate(Date date, byte accuracy, String comment) {
		super(comment, new DateWithAccuracy(date, accuracy));
	}

	public ParsedDate(DateWithAccuracy val, String comment) {
		super(comment, val);
	}

	public ParsedDate(Date lDate, byte lAccuracy, Date uDate, byte uAccuracy,
			String comment) {
		super(comment, new DateWithAccuracy(lDate, lAccuracy),
				new DateWithAccuracy(uDate, uAccuracy));
	}

	public ParsedDate(DateWithAccuracy lDateWithAccuracy,
			DateWithAccuracy uDateWithAccuracy, String comment) {
		super(comment, lDateWithAccuracy, uDateWithAccuracy);
		if (lDateWithAccuracy == null && uDateWithAccuracy == null) {
			throw new IllegalStateException();
		}
	}

	public ParsedDate(ParsedValue pv, String comment) {
		super(pv, comment);
	}

	public ParsedDate(Element element) {
		super(element);
		if (lowerBound == null && upperBound_def == null) {
			throw new IllegalStateException();
		}
	}

	private ParsedDate(ParsedDate other, Object value, String comment) {
		super(other, value, comment);
	}

	@Override
	public Object describer() {
		return DateWithAccuracy.class;
	}

	@Override
	@SuppressWarnings("unchecked")
	public <S> S[] getConvertedValue(Class<S> clazz) {
		if (clazz == Double.class) {
			if (isRange()) {
				return (S[]) new Double[] {
						(double) getLowerBound().getDateCode(),
						(double) getUpperBound().getDateCode() };
			} else
				return (S[]) new Double[] { (double) getUpperBound()
						.getDateCode() };
		}
		return null;
	}

	@Override
	public String getId() {
		return ID;
	}

	@Override
	public String getValueAsString() {

		if (isRange()) {
			StringBuilder bld = new StringBuilder(lowerBound.toString());
			bld.append(getDefaultRangeDelimeter());
			bld.append(upperBound_def.toString());
			return bld.toString();
		} else
			return upperBound_def.toString();
	}

	@Override
	protected DateWithAccuracy readSingleValue(Element element) {
		DateWithAccuracy dateVal = null;
		String valStr = element.getAttribute("value");
		String accuracyString = element.getAttribute("accuracy");
		byte accuracy = accuracyString.length() > 0 ? Byte
				.parseByte(accuracyString) : DateWithAccuracy.ACCURACY_YEAR;
		Date date;
		try {
			date = DateFormat.getDateInstance(DateFormat.LONG, Locale.US)
					.parse(valStr);
			dateVal = new DateWithAccuracy(date, accuracy);
		} catch (ParseException e) {
			e.printStackTrace();
			return null;
		}
		

		return dateVal;
	}

	@Override
	protected void writeSingleValue(Element valNode, DateWithAccuracy val) {

		valNode.setAttribute(
				"value",
				DateFormat.getDateInstance(DateFormat.LONG, Locale.US).format(
						val.getDate()));
		valNode.setAttribute("accuracy", "" + val.getAccuracy());

		
	}

	@Override
	protected boolean valueIsStoredInSingleString() {
		return false;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((upperBound_def == null) ? 0 : upperBound_def.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ParsedDate other = (ParsedDate) obj;
		if (upperBound_def == null) {
			if (other.upperBound_def != null)
				return false;
		} else if (!upperBound_def.equals(other.upperBound_def))
			return false;
		return true;
	}

	@Override
	public Class<DateWithAccuracy> getValueClass() {
		return DateWithAccuracy.class;
	}

	@Override
	public IHasValue clone(Object value, String comment) {

		if (!(value instanceof DateWithAccuracy || value instanceof DateWithAccuracy[]))
			return null;
		if (comment == null)
			comment = this.getComment();
		return new ParsedDate(this, value, comment);
	}

	@Override
	protected DateWithAccuracy readValue(String ubStr) {
		return null;
	}

	@Override
	protected String writeSingleValue(DateWithAccuracy val) {
		return null;
	}

}
